/*
 *文件作用: 声明内部类型和API实现
*/

#include <stdio.h>
#include "leptjson.h"
#include <assert.h>

//将json的相关数据封装，减少解析函数之间传递的参数个数
//暂只存放json字符串
typedef struct {
    const char* json;
} lept_context;

//比较c和ch是否相等
#define EXPECT(context, ch) \
do { \
    assert(*context->json == (ch)); \
} while(0)

//解析whitespace
static void lept_parse_whitespace(lept_context* c) {
    const char *p = c->json;
    //解析space, tab, line feed, carriage return
    while((*p != '\0') && (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r')) {
        p++;
    }
    c->json = p;
}

// //解析null值
// static int lept_parse_null(lept_context* c, lept_value* v) {
//     EXPECT(c, 'n');    
//     if (c->json[1] != 'u' || c->json[2] != 'l' || c->json[3] != 'l') {
//         return LEPT_PARSE_INVALID_VALUE;
//     }

//     c->json += 4;
//     v->type = LEPT_NULL;
//     return LEPT_PARSE_OK;
// }

// //解析true值
// static int lept_parse_true(lept_context* c, lept_value* v) {
//     EXPECT(c, 't');
//     if (c->json[1] != 'r' || c->json[2] != 'u' || c->json[3] != 'e') {
//         return LEPT_PARSE_INVALID_VALUE;
//     }

//     c->json += 4;
//     v->type = LEPT_TRUE;
//     return LEPT_PARSE_OK;
// }

// //解析false值
// static int lept_parse_false(lept_context* c, lept_value* v) {
//     EXPECT(c, 'f');
//     if (c->json[1] != 'a' || c->json[2] != 'l' || c->json[3] != 's' || c->json[4] != 'e') {
//         return LEPT_PARSE_INVALID_VALUE;
//     }

//     c->json += 5;
//     v->type = LEPT_FALSE;
//     return LEPT_PARSE_OK;
// }

//对 true, false, null 的合并解析
//参数表:
//  c: 保存json串的内容
//  v: 解析后保存数据的节点
//  expect_json: 期待的字符串
//  type_type: 期待的解析结果类型
static int lept_parse_tfn(lept_context* context, lept_value* v, char* expect_json, lept_type expect_type) {
    EXPECT(context, *expect_json);
    context->json++;
    expect_json++;
    while((*context->json != '\0') && (*expect_json != '\0')) {
        if (*context->json != *expect_json) {
            return LEPT_PARSE_INVALID_VALUE;
        }
        context->json++;
        expect_json++;
    }
    //未完成解析，json字符串非法
    if (*expect_json != '\0') {
        return LEPT_PARSE_INVALID_VALUE;
    }
    v->type = expect_type;
    return LEPT_PARSE_OK;
}

//解析 value = null / false / true
static int lept_parse_value(lept_context* c, lept_value* v) {
    switch (*c->json)
    {
    case 't':
        return lept_parse_tfn(c, v, "true", LEPT_TRUE);
    case 'f':
        return lept_parse_tfn(c, v, "false", LEPT_FALSE);
    case 'n':
        return lept_parse_tfn(c, v, "null", LEPT_NULL);
    case '\0':
        return LEPT_PARSE_EXPECT_VALUE;  //没有value
    default:
        return LEPT_PARSE_INVALID_VALUE;  //非法值
    }
}

//按照 whitespace - value - whitespace 的格式对json字符串进行解析
int lept_parse(lept_value* v, const char* json) {
    lept_context c;
    assert(v != NULL);  //第一个值不能是null
    c.json = json;
    v->type = LEPT_NULL;  //初始化为null类型
    lept_parse_whitespace(&c);
    int ret_value = lept_parse_value(&c, v);

    //以下是自己写的版本，实际操作就是解析空格，判断是否结束，可以直接调用解析空格的 API 来完成
    // while (*c.json != '\0') {
    //     //若已取得有效值，则判断字符串结束前是否还存在非空白字符，若存在则令返回值为Not_Singular
    //     if ((ret_value == LEPT_PARSE_OK) && !((*c.json == ' ' ) || (*c.json == '\t') || (*c.json == '\n') || (*c.json == '\r') || (*c.json == '\0'))) {
    //         ret_value = LEPT_PARSE_ROOT_NOT_SINGULAR;
    //     }
    //     (c.json)++;
    // }

    //若value解析成功，则继续解析value之后的所有空格，再判断是否结束。若未结束则判定为多值输入
    if (ret_value == LEPT_PARSE_OK) {
        lept_parse_whitespace(&c);
        if ((ret_value == LEPT_PARSE_OK) &&  (*c.json != '\0')) {
            v->type = LEPT_NULL;  //多值输入，将类型强制修改为null
            return LEPT_PARSE_ROOT_NOT_SINGULAR;
        }
    }
    return ret_value;
}

//返回节点的类型
lept_type lept_get_type(const lept_value* v) {
    return v->type;
}
